<template>
  <div class="ai-search-page">
    <el-card class="search-history-card">
      <div class="history-group" v-for="group in historyList" :key="group.tag">
        <div class="group-text">{{ group.tag }}</div>
        <div class="history-item" :class="currentTopicId === item.topic_id ? 'active' : ''" v-for="item in group.list" :key="item.topic_id" @click="handleEnterTopic(item)">
          <span v-if="!item.edit">{{ item.topic_name }}</span>
          <el-input v-else v-model="item.topic_name" @blur="handleTopicReName(item)" @click.native.stop/>
          <div @click.stop>
            <el-dropdown trigger="click" @command="(command) => handleTopicMenuClick(command, item)">
              <i class="iconfont icon-gengduo"></i>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item command="rename">重命名</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
        </div>
      </div>
      <div class="create-box">
        <el-button type="default" size="large" class="new-topic-btn" @click="handleNewTopic">
          <template #icon>
            <i class="iconfont icon-xinduihua"></i>
          </template>
          开启新对话
        </el-button>
      </div>
    </el-card>
    <el-card class="search-chat-card">
      <div class="answer-content" ref="answerRef">
<!--        <MarkdownComp content="### 1. 用户输入网址-->
<!--用户在浏览器的地址栏中输入网址（URL），例如 \`https://www.example.com\`。"></MarkdownComp>-->
        <div class="chat-item" v-for="chat in chatHistory" :key="chat.id">
          <div class="user-content">
            <div class="user-text">
              {{ chat.user }}
            </div>
          </div>
          <div class="aispire-content">
            <div class="ai-avatar">
              <div class="avatar"></div>
            </div>
            <div class="ai-text" v-if="!chat.loading">
<!--              {{ chat.aispire }}-->
              <MarkdownComp :content="chat.aispire"></MarkdownComp>
            </div>
            <i v-else class="iconfont icon-jiazaizhong loading"></i>
          </div>
        </div>
      </div>
      <div class="input-box">
<!--        <el-button type="default" size="large" class="new-topic-btn" @click="handleNewTopic">-->
<!--          <template #icon>-->
<!--            <i class="iconfont icon-xinduihua"></i>-->
<!--          </template>-->
<!--          开启新对话-->
<!--        </el-button>-->
        <el-input v-model="questionStr" size="large" clearable placeholder="请输入你想问的问题"  @keypress.enter="handleSendQuestion"></el-input>
        <el-button type="primary" size="large" :disabled="!questionStr" @click="handleSendQuestion">发送</el-button>
      </div>

    </el-card>
  </div>
</template>

<script setup>
import {ref, nextTick} from 'vue'
import { Plus } from '@element-plus/icons-vue'
import MarkdownComp from '../../components/markdown-comp.vue'
import {uuid} from "~/common/utils.js";
import api from '../../api/index.js'
import common from "~/common/common.js";
import {fetchEventSource} from '@microsoft/fetch-event-source'

const user = common.getLocalUser()
const uid = user.userId
const currentTopicId = ref('')
const historyList = ref([])
const setHistoryDataGroup = (historyData) => {
  let tag = ''
  let len = 0
  historyList.value = []
  historyData.forEach((item) => {
    item.tag = item.tag || '今天'
    if (tag !== item.tag) {
      len = historyList.value.length
      historyList.value[len] = {
        tag: item.tag,
        list: [],
        edit: false,
      }
      tag = item.tag
    }
    historyList.value[len].list.push(item)
  })
}
const getHistoryList = (init) => {
  api.historyTopicList({
    uid,
  }).then(res => {
    if (res.topic_list && res.topic_list.length) {
      setHistoryDataGroup(res.topic_list)
      currentTopicId.value = res.topic_list[0].topic_id
      if (init) {
        handleEnterTopic(res.topic_list[0])
      }
    }
  })
}
getHistoryList(true)
const handleTopicMenuClick = (command, item) => {
  item.edit = true
}
const handleTopicReName = async (item) => {
  await api.historyTopicRename({
    uid,
    topic_id: item.topic_id,
    new_name: item.topic_name
  })
  item.edit = false
}

const createTopicDialogVisible = ref(false)
const topicTitle = ref('')
const createTopicLoading = ref(false)
const handleNewTopic = () => {
  currentTopicId.value = ''
  chatHistory.value = []
}
const executeCreateTopic = async (topicName) => {
  let res
  try {
    res = await api.createTopic({
      uid,
      search_text: topicName
    })
  } catch(e){
    console.log(e)
  }
  return res
}
const handleCreateTopic = () => {
  if (!topicTitle.value) {
    return
  }
  createTopicLoading.value = true
  api.createTopic({
    uid,
    search_text: topicTitle.value
  }).then(res => {
    createTopicLoading.value = false
    if (res.topic_id) {
      ElMessage.success('创建对话成功')
      createTopicDialogVisible.value = false
    } else {
      ElMessage.error('创建对话失败')
    }
  }).catch(e => {
    createTopicLoading.value = false
    ElMessage.error('创建对话异常')
    console.log(e)
  })
}


const answerRef = ref()
const questionStr = ref('')
const chatHistory = ref([])
const handleEnterTopic = (topic) => {
  chatHistory.value = []
  currentTopicId.value = topic.topic_id
  questionStr.value = ''
  api.historyTopicDetail({
    uid,
    topic_id: currentTopicId.value
  }).then(res => {
    if (res.chat_history && res.chat_history.length) {
      res.chat_history.forEach(item => {
        item.id = item.id || uuid(12)
      })
      chatHistory.value = res.chat_history
      nextTick(() => {
        const top = answerRef.value.scrollHeight - answerRef.value.offsetHeight
        answerRef.value.scrollTop = top
      })
    }
  })
}
const EventStreamContentType = 'text/event-stream; charset=utf-8'
const questionSubmit = (text, index) => {
  return new Promise((resolve, reject) => {
    const ctrlAbout = new AbortController();
    fetchEventSource('/aispire/chat', {
      method: 'POST',
      headers: {
        "Content-Type": 'application/json',
        'Accept': '*/*',
      },
      openWhenHidden: true,
      body: JSON.stringify({
        uid,
        topic_id: currentTopicId.value,
        search_text: text
      }),
      signal: ctrlAbout.signal,
      onmessage(event) {
        // 在这里操作流式数据
        // console.log('message', event)
        chatHistory.value[index].loading = false
        chatHistory.value[index].aispire += event.data
      },
      onopen(response){
        console.log('open', response)
        if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
          //return // everything's good
        } else if (response.status >= 400 && response.status < 500 && response.status !== 429) {
          // client-side errors are usually non-retriable:
          reject()
          throw new Error()
        } else {
          reject()
          throw new Error()
        }
      },
      onclose(e) {
        console.log('close', e)
        // 关闭流
        // 中断流式返回
        ctrlAbout.abort()
        resolve()
      },
      onerror(error) {
        // 返回流报错
        console.info(error);
        // 中断流式返回
        ctrlAbout.abort()
        reject()
        throw error // 直接抛出错误，避免反复调用
      }
    })
  })

}
const handleSendQuestion = async () => {
  const text = questionStr.value
  if (!text) {
    return
  }
  const id = uuid(12)
  let isNewTopic = false
  if (!currentTopicId.value) {
    const topic = await executeCreateTopic(text)
    if (topic && topic.topic_id) {
      currentTopicId.value = topic.topic_id
      isNewTopic = true
    } else {
      ElMessage.error('对话创建失败')
    }
  }
  if (currentTopicId.value) {
    questionStr.value = ''
    chatHistory.value.push({
      id,
      user: text,
      aispire: '',
      loading: true
    })
    const len = chatHistory.value.length
    questionSubmit(text,len - 1).then(() => {
      nextTick(() => {
        answerRef.value.scrollTop = answerRef.value.scrollHeight - answerRef.value.offsetHeight
        if (isNewTopic) {
          getHistoryList()
        }
      })
    })
  }
}
</script>

<style scoped lang="scss">
$avatar-bg-size: 3.4rem;
.ai-search-page {
  position: relative;
  height: 100%;
  display: flex;
  justify-content: space-between;
}

.search-history-card {
  position: relative;
  width: 20%;
  max-width: 20%;
  min-width: 20%;
  .create-box{
    position: absolute;
    bottom: 0;
    left:0;
    width: 100%;
    text-align: center;
    padding: 10px 0;
    background: #fff;
    //.el-button{
    //  display: inline-block;
    //}
  }
}

.search-chat-card {
  position: relative;
  width: 79%;
  max-width: 79%;
  min-width: 79%;

  .answer-content {
    position: relative;
    width: 100%;
    max-height: calc(100% - 72px);
    font-size: 1.4rem;
  }
  .chat-item{
    position: relative;
    padding: 3.5rem 2rem;
    .user-content{
      position: relative;
      width: 100%;
      display: flex;
      justify-content: flex-end;
      .user-avatar{
        position: relative;
        width: $avatar-bg-size;
        min-width: $avatar-bg-size;
        height: $avatar-bg-size;
        border-radius: $avatar-bg-size;
        margin-right: 1.2rem;
        background: #fff;
        .avatar{
          position: absolute;
          top: 15%;
          left: 15%;
          width: 70%;
          height: 70%;
          border-radius: $avatar-bg-size;
          background-size: 100% 100%;
        }
      }
      .user-text{
        position: relative;
        background: #eff6ff;
        padding: 5px 8px;
        border-radius: 5px;
        line-height: 2.4rem;
        .iconfont{
          position: absolute;
          font-size: 1.4rem;
          height: 1.4rem;
          color: var(--el-color-success-light-3);
          top: 1.7rem;
          margin-top: -0.7rem;
          left: -1.2rem;
          line-height: 1.4rem;
          transform: rotateZ(-180deg);
          transform-origin: center;
        }
      }
    }
    .aispire-content{
      position: relative;
      display: flex;
      width: 100%;
      align-items: flex-start;
      margin-top: 2rem;
      .icon-jiazaizhong{
        display: inline-block;
        transform-origin: center;
        font-size: 2.4rem;
        width: 2.4rem;
        height: 2.4rem;
      }
      .ai-avatar{
        position: relative;
        width: $avatar-bg-size;
        min-width: $avatar-bg-size;
        height: $avatar-bg-size;
        border-radius: $avatar-bg-size;
        margin-right: 1.2rem;
        background: #fff;
        border: 1px solid var(--el-color-info);
        .avatar{
          position: absolute;
          top: 15%;
          left: 15%;
          width: 70%;
          height: 70%;
          border-radius: $avatar-bg-size;
          background-image: url("../../assets/images/logo.png");
          background-size: 100% 100%;
        }
      }
      .ai-text{
        position: relative;
        background: #fff;
        //padding: 8px;
        border-radius: 5px;
        line-height: 2.4rem;
        .iconfont{
          position: absolute;
          font-size: 1.4rem;
          height: 1.4rem;
          color: #fff;
          top: 1.7rem;
          margin-top: -0.7rem;
          right: -1.2rem;
          line-height: 1.4rem;
        }
      }
    }
  }

  .input-box {
    position: absolute;
    bottom: 0;
    width: calc(100% - 40px);
    padding: 20px 20px 20px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .el-button {
      margin-left: 5px;
    }
    .new-topic-btn{
      position: absolute;
      top: 20px;
      left: 50%;
      margin-left: 0;
      transform: translateX(-50%);
    }
  }
}
.new-topic-btn{
  font-size: 1.2rem;
  .iconfont{
    font-size: 1.8rem;
  }
}
.history-group {
  margin: 20px 0;

  .group-text {
    margin-bottom: 10px;
    font-size: 1.4rem;
    color: var(--el-text-color-secondary);
  }

  .history-item {
    position: relative;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 1.2rem;
    height: 3.2rem;
    padding: 0 1.5rem;
    cursor: pointer;
    border-radius: 3px;
    &.active{
      background: #D9EFFA;
    }
    span{
      display: inline-block;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      width: 80%;
      max-width: 80%;
    }
    .iconfont{
      font-size: 1.4rem;
    }
  }
}

</style>
